// @ts-nocheck
class MyPromise {
	//定义状态
	static PENDING = 'pending'
	static FULFILLED = 'fulfilled'
	static REJECTED = 'rejected'

	constructor(func) {
		// 初始化 状态
		this.PromiseState = MyPromise.PENDING
		// 初始化promise 返回的结果
		this.PromiseResult = null
		// 定义成功时的回调暂存数组
		this.onFulfilledCallbacks = []
		// 定义失败时的回调数组
		this.onRejectedCallbacks = []
		// 处理 throw 的异常情况
		try {
			// new MyPromise 时传入的立即执行函数 绑定动态的this
			func(this.resolve.bind(this), this.reject.bind(this))
		} catch (error) {
			this.reject(error)
		}
	}

	resolve(result) {
		// 只有 当前 promise 为 pending 状态才能 转换状态
		if (this.PromiseState === MyPromise.PENDING) {
			// 处理异步的情况 可以利用微任务队列(微任务) 或者 定时器函数(宏任务)
			setTimeout(() => {
				// 修改状态
				this.PromiseState = MyPromise.FULFILLED
				// 保存 结果
				this.PromiseResult = result
				// 查看 成功时的回调暂存数组 并依次执行
				this.onFulfilledCallbacks.forEach((callback) => {
					callback(result)
				})
			})
		}
	}

	reject(reason) {
		if (this.PromiseState === MyPromise.PENDING) {
			setTimeout(() => {
				this.PromiseState = MyPromise.REJECTED
				this.PromiseResult = reason
				this.onRejectedCallbacks.forEach((callback) => {
					callback(reason)
				})
			})
		}
	}

	/**
	 * [注册fulfilled状态/rejected状态对应的回调函数]
	 * @param {function} onFulfilled  fulfilled状态时 执行的函数
	 * @param {function} onRejected  rejected状态时 执行的函数
	 * @returns {function} newPromsie  返回一个新的promise对象
	 */
	then(onFulfilled, onRejected) {
		// 参数校验
		onFulfilled =
			typeof onFulfilled === 'function' ? onFulfilled : (value) => value
		onRejected =
			typeof onRejected === 'function'
				? onRejected
				: (reason) => {
						throw reason
				  }
		// then 函数 必须返回一个 新的 promise 对象
		let promise = new MyPromise((resolve, reject) => {
			// 判断 当前promise 的状态 并 做出相应的处理
			if (this.PromiseState === MyPromise.FULFILLED) {
				setTimeout(() => {
					try {
						let x = onFulfilled(this.PromiseResult)
						this.#resolvePromise(promise, x, resolve, reject)
					} catch (e) {
						reject(e)
					}
				})
			} else if (this.PromiseState === MyPromise.REJECTED) {
				setTimeout(() => {
					try {
						let x = onRejected(this.PromiseResult)
						this.#resolvePromise(promise, x, resolve, reject)
					} catch (e) {
						reject(e)
					}
				})
			} else if (this.PromiseState === MyPromise.PENDING) {
				// 如果 当前的 promise 为 pending 状态 保留 当前函数到 对应的回调暂存数组中
				this.onFulfilledCallbacks.push(() => {
					try {
						let x = onFulfilled(this.PromiseResult)
						this.#resolvePromise(promise, x, resolve, reject)
					} catch (e) {
						reject(e)
					}
				})
				this.onRejectedCallbacks.push(() => {
					try {
						let x = onRejected(this.PromiseResult)
						this.#resolvePromise(promise, x, resolve, reject)
					} catch (e) {
						reject(e)
					}
				})
			}
		})

		return promise
	}
	/**
	 * 对resolve()、reject() 进行改造增强 针对resolve()和reject()中不同值情况 进行处理
	 * @param  {promise} promise promise1.then方法返回的新的promise对象
	 * @param  {[type]} x         promise1中onFulfilled或onRejected的返回值
	 * @param  {[type]} resolve   promise的resolve方法
	 * @param  {[type]} reject    promise的reject方法
	 */
	#resolvePromise(promise, x, resolve, reject) {
		// 如果then 返回的是 同一个promise 循环调用则报错
		if (x === promise) {
			return reject(new TypeError('Chaining cycle detected for promise'))
		}
		// 如果then 返回的是 promise 实例对象则拿到 x 的最终 promise 的状态
		if (x instanceof MyPromise) {
			// 对 then 返回的是 promise 的三种不同的状态分别处理
			if (x.PromiseState === MyPromise.PENDING) {
				// 如果 是一个 pending 对象 继续递归执行直到拒绝或者成功
				x.then((y) => {
					this.#resolvePromise(promise, y, resolve, reject)
				}, reject)
			} else if (x.PromiseState === MyPromise.FULFILLED) {
				resolve(x.PromiseResult)
			} else if (x.PromiseState === MyPromise.REJECTED) {
				reject(x.PromiseResult)
			}
		} // 如果如果then 返回的是一个 thenable 对象
		else if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
			// 拿到 thenable 对象的 then函数
			try {
				var then = x.then
			} catch (e) {
				return reject(e)
			}

			// 如果 then 是一个函数 执行并将this 指向 当前的 thenable 对象
			if (typeof then === 'function') {
				// 避免循环引用
				let called = false
				try {
					then.call(
						x,
						(y) => {
							// thenable 对象返回 resolve
							if (called) return
							called = true
							this.#resolvePromise(promise, y, resolve, reject)
						},
						(r) => {
							// thenable 对象返回 reject 直接
							if (called) return
							called = true
							reject(r)
						}
					)
				} catch (e) {
					if (called) return
					called = true

					reject(e)
				}
			} // then 返回的如果是普通的对象属性
			else {
				resolve(x)
			}
		} //  then 返回的非 promise 值非 thenable 对象
		else {
			return resolve(x)
		}
	}
	static resolve(value) {
		// 对 promise 、 非promise 、 普通值 的处理
		// promise
		if (value instanceof MyPromise) {
			return value
		}
		// thenable 对象
		if (
			value instanceof Object &&
			'then' in value &&
			typeof value.then === 'function'
		) {
			return new MyPromise((resolve, reject) => value.then(resolve, reject))
		}
		// 普通值
		return new MyPromise((resolve, reject) => resolve(value))
	}
	static reject(reason) {
		return new MyPromise((resolve, reject) => reject(reason))
	}
	catch(onRejected) {
		return this.then(undefined, onRejected)
	}
	finlay(callback) {
		const p = this.constructor
		return p.then(
			(value) => P.resolve(callback()).then(() => value),
			(reason) =>
				P.resolve(callback()).then(() => {
					throw reason
				})
		)
	}
	/**
	 * 1. 返回一个新的promise 实例
	 * 2. 参数是一个可迭代promise 对象
	 * 3. 参数中存在非promise 则按顺序返回
	 * 4. 等待全部成功 返回结果数组  / 或者一个失败返回失败原因
	 * 5. 若果是一个空的可迭代对象 返回一个 resolve 状态的promise
	 * @param {*} promiseArr
	 */
	static all(promiseArr) {
		return new MyPromise((resolve, reject) => {
			if (!Array.isArray(promiseArr))
				return reject(new TypeError('Argument is not iterable'))
			if (promiseArr.length === 0) return resolve(promiseArr)
			let result = []
			promiseArr.forEach((item, index) => {
				if (item instanceof MyPromise) {
					MyPromise.resolve(item).then(
						(value) => {
							result[index] = value
							promiseArr.length === result.length && resolve(result)
						},
						(reason) => reject(reason)
					)
				} else {
					result[index] = item
					promiseArr.length === result.length && resolve(result)
				}
			})
		})
	}
	/**
	 * 1. 返回一个新的Promise
	 * 2. 等待并返回所有的结果
	 * 3. 存在 非 promise 转成promise处理
	 * 4. 若果是一个空的可迭代对象 返回一个 resolve 状态的promise
	 * [{status: 'fulfilled', value: 3},{status: 'rejected', value: 3} ]
	 */
	static allSettled(promiseArr) {
		return new MyPromise((resolve, reject) => {
			if (!Array.isArray(promiseArr))
				return reject(new TypeError('Argument is not iterable'))
			if (!promiseArr.length) return resolve(promiseArr)
			let result = []
			promiseArr.forEach((item, index) => {
				MyPromise.resolve(item).then(
					(value) => {
						result[index] = { status: MyPromise.FULFILLED, value }
						result.length === promiseArr.length && resolve(result)
					},
					(reason) => {
						result[index] = { status: MyPromise.REJECTED, reason }
						result.length === promiseArr.length && resolve(result)
					}
				)
			})
		})
	}
	/**
	 * 和 all 相反
	 * 1. 一个 成功 或者 全部失败 时返回结果
	 * 2. 若果是一个空的可迭代对象 返回一个 reject 状态的 异常 AggregateError
	 * @param {*} promiseArr
	 * @returns
	 */
	static any(promiseArr) {
		return new MyPromise((resolve, reject) => {
			if (!Array.isArray(promiseArr))
				return reject(new TypeError('Argument is not iterable'))
			if (!promiseArr.length)
				return reject(new AggregateError('All promises were rejected'))
			let result = []
			promiseArr.forEach((item, index) => {
				MyPromise.resolve(item).then(
					(value) => {
						resolve(value)
					},
					(reason) => {
						result[index] = reason
						result.length === promiseArr.length &&
							reject(new AggregateError(result))
					}
				)
			})
		})
	}
	/**
	 * 返回一个新的promise
	 * 1. 返回第一个结果 无论成或则失败
	 * 2. 如果传的迭代是空的，则返回的 promise 将永远等待。
	 * @param {*} promiseArr
	 * @returns
	 */
	static race(promiseArr) {
		return new MyPromise((resolve, reject) => {
			if (!Array.isArray(promiseArr))
				return reject(new TypeError('Argument is not iterable'))
			if (promiseArr.length > 0) {
				promiseArr.forEach((item) => {
					MyPromise.resolve(item).then(resolve, reject)
				})
			}
		})
	}
}
